from Utilities import *
__license__ = "GPLv2"
__version__ = "1.0-0"
__doc__ = """\
Pystalt.PackageManager

usage:
	import Pystalt.PackageManager as PM
	import Pygmund.Id as Id
	
	p = PM.Init(Id.Init("id/cognition.conf").Get("PYSTALT"))
	
	r = p.List()
	
	r = p.Create("chromify")
	r = p.Build("chromify")
	r = p.Uninstall("chromify")
	r = p.Inspect("chromify")
	r = p.List("chromify")
	r = p.Install("chromify")
	r = p.Upgrade("chromify")
	r = p.Build("chromify")

"""

class Init:
	def __init__(self, conf):
		self.package_dir = conf["package-dir"]
		self.data_dir = conf["data-dir"]
		self.package_ext = conf["package-extension"]
		self.ego_dir = conf["ego-dir"]
		self.superego_dir = conf["superego-dir"]
		self.modules_dir = conf["modules-dir"]
		self.id_dir = conf["id-dir"]
		self.manifest_template = {
									"id" : "",
									"name" : "",
									"version" : "",
									"license" : "",
									"description" : "",
									"update-url" : "",
									"maintainer" : {
										"name" : "",
										"email" : "",
										"company" : "",
										"website" : ""
									},
									"data" : []
								}
		
	def List(self, app=False):
		# Get list of Applications, or display single app's Manifest info.
		apps = loadjson(AddSep(self.data_dir) + "Applications")
		if not apps[0]:
			return (False, apps[1])
		else:
			apps = apps[1]
		if not app:
			# Return list of all apps...
			return (True, print_json(apps))
		else:
			# Return single app...
			if app in apps:
				manifest = load_manifest(self.data_dir, app)
				if not manifest[0]:
					return (False, "Could not get Application data.")
				else:
					manifest = manifest[1]
				return (True, print_json(manifest))
			else:
				return (False, "Application not found.")
			
		
	def updateInstalledAppsList(self, app):
		manifest = load_manifest(self.data_dir, app)
		if not manifest[0]:
			return (False, manifest[1])
		else:
			manifest = manifest[1]
		apps = loadjson(AddSep(self.data_dir) + "Applications")
		if not apps[0]:
			return (False, apps[1])
		else:
			apps = apps[1]
		apps[app] = {}
		apps[app]["version"] = manifest["version"]
		apps[app]["license"] = manifest["license"]
		apps[app]["description"] = manifest["description"]
		apps[app]["maintainer"] = manifest["maintainer"]
		apps[app]["installed"] = timestamp()
		r = savejson(AddSep(self.data_dir) + "Applications", apps)
		if not r[0]:
			return (False, r[1])
		else:
			return (True, "Applications list updated!")
		
	def Install(self, app):
		# Install application
		if app.endswith(self.package_ext):
			app = rmExt(app, self.package_ext)
		if not check_path(AddSep(self.package_dir) + app + self.package_ext):
			return (False, "Could not locate package '%s'" % app)
		r = unpack(self.package_dir, app, self.package_ext)
		if not r[0]:
			return (False, "Could not extract package (%s)" % r[1])
		r = self.updateInstalledAppsList(app)
		if not r[0]:
			return (False, "Package installed, but the application list could not be updated (%s)" % r[1])
		return (True, "Package installed!")
		
	def Uninstall(self, app):
		# Uninstall application
		manifest = load_manifest(self.data_dir, app)
		if not manifest[0]:
			return (False, manifest[1])
		else:
			manifest = manifest[1]
		for f in manifest["data"]:
			r = rm(f)
			if not r[0]:
				return (False, r[1])
		# Update Applications list...
		apps = loadjson(AddSep(self.data_dir) + "Applications")
		if not apps[0]:
			return (False, "Application uninstalled, however there was an error updating the Applications listing. (%s)" % apps[1])
		else:
			apps = apps[1]
		if app in apps:
			del apps[app]
		r = savejson(AddSep(self.data_dir) + "Applications", apps)
		if not r[0]:
			return (False, "Application uninstalled, however an error occured while saving changes to the Applications listing. (%s)" % r[1])
		return (True, "Application successfully uninstalled!")
		
	def Get(self, url):
		info = loadwebjson(url)
		if not info[0]:
			return (False, info[1])
		else:
			info = info[1]
		app = info["id"]
		r = download_pkg(info["download-url"], AddSep(self.package_dir) + app + self.package_ext)
		if not r[0]:
			return (False, "Failed to download package from %s (%s)" % (info["download-url"], r[1]))
		return (True, "Package downloaded to: %s" % self.package_dir)
	
	def Update(self, app):
		# Update application
		manifest = load_manifest(self.data_dir, app)
		if not manifest[0]:
			return (False, manifest[1])
		else:
			manifest = manifest[1]
		info = loadwebjson(manifest["update-url"])
		if not info[0]:
			return (False, "Could not retrieve update information (%s)" % info[1])
		else:
			info = info[1]
		if info["version"] > manifest["version"]:
			r = self.Get(manifest["update-url"])
			if not r[0]:
				return (False, "Failed to download update (%s)" % r[1])
			r = self.Install(app)
			if not r[0]:
				return (False, "Could not install update (%s)" % r[1])
			return (True, "Package '%s' successfully updated!" % app)
		else:
			return (True, "Package '%s' is already up to date." % app)
		
	def Build(self, app):
		# Compile application files into a Package
		manifest = load_manifest(self.data_dir, app)
		if not manifest[0]:
			return (False, manifest[1])
		else:
			manifest = manifest[1]
		r = pack(manifest["data"], app, self.package_ext, self.package_dir)
		if not r[0]:
			return (False, r[1])
		return (True, r[1])
		
	def Create(self, app):
		# Create skeleton of app, if app doesn't already exist on the system.
		if check_path(AddSep(self.ego_dir) + app):
			return (False, "Error: Application '%s' already exists." % app)
		r = mk_dir(AddSep(self.ego_dir) + app)
		if not r[0]:
			return (False, r[1])
		r = mk_dir(AddSep(self.ego_dir) + AddSep(app) + "libs")
		if not r[0]:
			return (False, r[1])
		r = mk_dir(AddSep(self.data_dir) + app)
		if not r[0]:
			return (False, r[1])
		r = save_manifest(self.data_dir, app, self.manifest_template)
		if not r[0]:
			return (False, r[1])
		return (True, "Application Skeleton created!")
	
	def Inspect(self, app):
		# View Application Manifest from Package
		manifest = load_pkg_manifest(AddSep(self.package_dir) + app + self.package_ext, generate_manifest_path(app))
		if not manifest[0]:
			return (False, "Error retrieving Application information (%s)" % manifest[1])
		else:
			return (True, print_json(manifest[1]))
